use std::{cell::Cell, path::PathBuf};

use thunderdome::Index;
use uuid::Uuid;
use QcCore::ecs::{component::Component, components::light::LightType};
use QcUI::{
    component::UiNode,
    core::uiBind::{JsUiBind, JsUiBindData},
};

use crate::panel::{ResFile, ResItem};

use super::component_data::ComponentData;

#[derive(Hash, Clone, Copy, PartialEq, Eq, Debug)]
pub enum ObjectType {
    GameObject,
    UiObject,
}

pub enum GameObjectType {
    /// 空节点
    None,
    /// 平面
    Plane,
    /// 立方体
    Cube,
    /// 球
    Ball,
    /// 胶囊
    Capsule,
    /// 猴头
    Monkey,

    Canvas,
}

#[derive(PartialEq)]
pub enum UiType {
    /// 按钮
    Button,
    /// 标签
    Label,
    /// 输入框
    TextBox,
    /// 布局
    Panel,
    /// 网格
    Grid,
    /// 单选框
    RadioBox,
    /// 多选框
    CheckBox,
}

#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum ComponentType {
    Camera,
    Light,
    MaterialRender,
    MeshRender,
    SkyBox,
    Transform,
    JsComponent,
    Other,

    // ui相关
    Widget,
    Button,
    Laebl,
    TextBox,
    Grid,
    Panel,
    Image,
}

impl ComponentType {
    pub fn list() -> Vec<ComponentType> {
        vec![
            Self::Camera,
            Self::Light,
            Self::MaterialRender,
            Self::MeshRender,
            Self::SkyBox,
            Self::Transform,
            Self::Other,
        ]
    }
}

impl Into<String> for ComponentType {
    fn into(self) -> String {
        match self {
            ComponentType::Camera => "Camera".to_string(),
            ComponentType::Light => "Light".to_string(),
            ComponentType::MaterialRender => "MaterialRender".to_string(),
            ComponentType::MeshRender => "MeshRender".to_string(),
            ComponentType::SkyBox => "SkyBox".to_string(),
            ComponentType::Transform => "Transform".to_string(),
            ComponentType::Other => "Other".to_string(),
            ComponentType::JsComponent => "JsComponent".to_string(),
            ComponentType::Widget => "Widget".to_string(),
            ComponentType::Button => "Button".to_string(),
            ComponentType::Laebl => "Laebl".to_string(),
            ComponentType::TextBox => "TextBox".to_string(),
            ComponentType::Grid => "Grid".to_string(),
            ComponentType::Panel => "Panel".to_string(),
            ComponentType::Image => "Image".to_string(),
        }
    }
}

impl<'a> Into<&'a str> for ComponentType {
    fn into(self) -> &'a str {
        match self {
            ComponentType::Camera => "Camera",
            ComponentType::Light => "Light",
            ComponentType::MaterialRender => "MaterialRender",
            ComponentType::MeshRender => "MeshRender",
            ComponentType::SkyBox => "SkyBox",
            ComponentType::Transform => "Transform",
            ComponentType::Other => "Other",
            ComponentType::JsComponent => "JsComponent",
            ComponentType::Widget => "Widget",
            ComponentType::Button => "Button",
            ComponentType::Laebl => "Laebl",
            ComponentType::TextBox => "TextBox",
            ComponentType::Grid => "Grid",
            ComponentType::Panel => "Panel",
            ComponentType::Image => "Image",
        }
    }
}

impl Into<ComponentType> for &mut Component {
    fn into(self) -> ComponentType {
        match self {
            Component::Camera(_) => ComponentType::Camera,
            Component::Light(_) => ComponentType::Light,
            Component::MaterialRender(_) => ComponentType::MaterialRender,
            Component::MeshRender(_) => ComponentType::MeshRender,
            Component::SkyBox(_) => ComponentType::SkyBox,
            Component::Transform(_) => ComponentType::Transform,
            Component::Other(_) => ComponentType::Other,
            Component::PointLight(_) => ComponentType::Light,
            Component::AmbientBoxLight(_) => ComponentType::Light,
            Component::AmbientSphereLight(_) => ComponentType::Light,
            Component::SpotLight(_) => ComponentType::Light,
            Component::DirectionalLight(_) => ComponentType::Light,
        }
    }
}

impl Into<ComponentType> for &Component {
    fn into(self) -> ComponentType {
        match self {
            Component::Camera(_) => ComponentType::Camera,
            Component::Light(_) => ComponentType::Light,
            Component::MaterialRender(_) => ComponentType::MaterialRender,
            Component::MeshRender(_) => ComponentType::MeshRender,
            Component::SkyBox(_) => ComponentType::SkyBox,
            Component::Transform(_) => ComponentType::Transform,
            Component::Other(_) => ComponentType::Other,
            Component::PointLight(_) => ComponentType::Light,
            Component::AmbientBoxLight(_) => ComponentType::Light,
            Component::AmbientSphereLight(_) => ComponentType::Light,
            Component::SpotLight(_) => ComponentType::Light,
            Component::DirectionalLight(_) => ComponentType::Light,
        }
    }
}

impl Into<ComponentType> for UiNode {
    fn into(self) -> ComponentType {
        match self {
            UiNode::Button(_) => ComponentType::Button,
            UiNode::Grid(_) => ComponentType::Grid,
            UiNode::Panel(_) => ComponentType::Panel,
            UiNode::Label(_) => ComponentType::Laebl,
            UiNode::TextBox(_) => ComponentType::TextBox,
            UiNode::Image(_) => ComponentType::Image,
            UiNode::Other(_) => ComponentType::Other,
        }
    }
}

impl Into<ComponentType> for &UiNode {
    fn into(self) -> ComponentType {
        match self {
            UiNode::Button(_) => ComponentType::Button,
            UiNode::Grid(_) => ComponentType::Grid,
            UiNode::Panel(_) => ComponentType::Panel,
            UiNode::Label(_) => ComponentType::Laebl,
            UiNode::TextBox(_) => ComponentType::TextBox,
            UiNode::Image(_) => ComponentType::Image,
            UiNode::Other(_) => ComponentType::Other,
        }
    }
}

pub enum EditorMessage {
    GoTo(Page),
    GoToEditor(PathBuf, String),
    AddGameObject(GameObjectType),
    RemoveGameObject(Index),
    RemoveUiNode(Index),
    AddUi(UiType),
    AddLight(LightType),
    AddComponent(ComponentData),
    SetMaterial(String),
    /// String 是材质的路径
    SetTexture(String),
    SetMesh(String),
    PlayGame(String),
    OpenScene(ResFile),
    SaveScene,
    AddUiBind(Uuid, JsUiBind),
}

#[derive(Eq, PartialEq, Hash, Clone, Copy)]
pub enum Page {
    ProjectHub,
    Editor,
}

#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub enum PageParams {
    ProjectHub(),
    Editor { name: String, path: PathBuf },
}

impl Into<Page> for PageParams {
    fn into(self) -> Page {
        match self {
            PageParams::ProjectHub() => Page::ProjectHub,
            PageParams::Editor { .. } => Page::Editor,
        }
    }
}
